package org.andolphin.client;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.andolphin.client.utils.DateUtils;
import org.andolphin.client.utils.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class Result implements Serializable {

    private static final long serialVersionUID = 1L;

    public static final String TAG = Result.class.getName();

    public static final String KEY = "org.andolphin.client.Result";

    // 结果字段名
    public static final class Field implements Serializable {
        private static final long serialVersionUID = 1L;
        public static final String CODE = "code";
        public static final String MESSAGE = "message";
        public static final String DATA = "data";
        public static final String ERROR_MESSAGE = "error_message";
    }

    public static final class Data implements Serializable {
        private static final long serialVersionUID = 1L;

        private JSONObject rawData;

        public Data(JSONObject rawData) {
            this.rawData = rawData;
        }

        public JSONObject getRawData() {
            return rawData;
        }

        public void setRawData(JSONObject rawData) {
            this.rawData = rawData;
        }

        public String getString(String key) {
            try {
                return rawData.getString(key);
            } catch (Exception e) {
                Log.d(TAG, StringUtils.digMessage(e), e);
                return null;
            }
        }

        public Integer getInt(String key) {
            try {
                return rawData.getInt(key);
            } catch (Exception e) {
                Log.d(TAG, StringUtils.digMessage(e), e);
                return null;
            }
        }

        public Date getDate(String key) {
            try {
                String dateStr = rawData.getString(key);
                return DateUtils.parseDateTime(dateStr);
            } catch (JSONException e) {
                Log.d(TAG, StringUtils.digMessage(e), e);
                return null;
            }
        }

        public Data getData(String key) {
            try {
                JSONObject json = rawData.getJSONObject(key);
                return new Data(json);
            } catch (JSONException e) {
                Log.d(TAG, StringUtils.digMessage(e), e);
                return null;
            }
        }

        public String[] getStringArray(String key) {
            try {
                JSONArray array = rawData.getJSONArray(key);
                int length = array.length();
                String[] results = new String[length];
                for (int i = 0; i < array.length(); i++) {
                    results[i] = array.getString(i);
                }
                return results;
            } catch (JSONException e) {
                Log.d(TAG, StringUtils.digMessage(e), e);
                return new String[0];
            }
        }

        @SuppressWarnings("unchecked")
        public List<String> keys() {
            List<String> result = new ArrayList<String>();
            Iterator keys = rawData.keys();
            while (keys.hasNext()) {
                result.add((String) keys.next());
            }
            return result;
        }
    }

    // 登陆成功
    public static final int CODE_LOGIN_SUCESS = 0;
    // 登陆失败：用户名不存在
    public static final int CODE_LOGIN_FAIL_USER = 2;
    // 登陆失败：密码不正确
    public static final int CODE_LOGIN_FAIL_PASSWD = 3;
    // 验证成功：网络故障
    public static final int CODE_AUTH_FAIL_NET = 1;
    // 验证成功：非法TOKEN
    public static final int CODE_AUTH_FAIL_INVALID = 2;
    // 验证成功：过期
    public static final int CODE_AUTH_FAIL_EXPIRED = 3;
    // 注册成功
    public static final int CODE_REGISTER_SUCCESS = 0;
    // 注册成功: 用户名重复
    public static final int CODE_REGISTER_FAIL_USER_DUPLICATE = 1;
    // 网络故障
    public static final int CODE_NET_ERROR = -1;
    // 服务器故障
    public static final int CODE_SERVER_ERROR = -2;
    // 服务器返回数据错误
    public static final int CODE_DATA_ERROR = -3;
    // 操作成功
    public static final int CODE_SUCCESS = 0;
    // 操作失败
    public static final int CODE_FAILURE = 1;
    // 输入错误
    public static final int CODE_INPUT_ERROR = -99;
    // 位置错误
    public static final int CODE_UNKNOWN_ERROR = -100;

    // Http响应的原始信息
    public static final String KEY_RESPONSE_MESSAGE = "RESPONSE_MESSAGE";

    private int code;

    private String message;

    private Data data;

    public Result(JSONObject rawData) {
        try {
            this.data = new Data(rawData.getJSONObject(Field.DATA));
        } catch (JSONException e) {
            this.data = new Data(null);
        }
        try {
            this.code = rawData.getInt(Field.CODE);
        } catch (JSONException e) {
            this.code = CODE_FAILURE;
        }
        try {
            this.message = rawData.getString(Field.MESSAGE);
        } catch (JSONException e) {
            this.message = "";
        }
    }

    public Result(int code, String message, Data data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Result() {

    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    public Map<String, String> getErrorMessages() {
        Map<String, String> result = new HashMap<String, String>();
        if (CODE_INPUT_ERROR == this.getCode()) {
            Data errors = this.data.getData(Field.ERROR_MESSAGE);
            for (String key : errors.keys()) {
                result.put(key, errors.getString(key));
            }
        }
        return result;
    }

    public static final Result NETWORK_ERROR = new Result() {
        private static final long serialVersionUID = 1L;

        @Override
        public int getCode() {
            return CODE_NET_ERROR;
        }

        @Override
        public String getMessage() {
            return "network error!";
        }
    };

    public static final Result SERVER_ERROR = new Result() {
        private static final long serialVersionUID = 1L;

        @Override
        public int getCode() {
            return CODE_SERVER_ERROR;
        }

        @Override
        public String getMessage() {
            return "network error!";
        }
    };

    public static final Result DATA_ERROR = new Result() {
        private static final long serialVersionUID = 1L;

        @Override
        public int getCode() {
            return CODE_DATA_ERROR;
        }
    };


    public static final Result UNKNOWN_ERROR = new Result() {
        private static final long serialVersionUID = 1L;

        @Override
        public int getCode() {
            return CODE_UNKNOWN_ERROR;
        }
    };

    /**
     * 从JSONObject创建一个Result实例
     * 
     * @param json Json原始数据。
     * @return Result实例
     */
    public static Result createFromJSONObject(JSONObject json) {
        return new Result(json);
    }
}
